//
//  Router.swift
//  DYSwiftFramework
//
//  Created by 黄德玉 on 2018/8/6.
//  Copyright © 2018年 none. All rights reserved.
//

//foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose
//\_/ \________________/ \_________/ \__/\____________________/\____________________/ \__/
//    |           |              |        |            |                      |            |
//scheme   userinfo          host     port         path                  query       fragment


import UIKit
import Flutter
import FlutterPluginRegistrant

//路由节点，在添加路由表的时候，需要节点和页面一一对应，用于每个页面持有
public struct RouterNode {
    // 路由共有部分
    public var name:String                  // 节点名称
    public var instance: String             // 节点实例,viewController的名字
    public var unique:Bool = false          // 独一无二的，不能创建多个实例
    public var meta:[String : Any]?          // 路由节点元信息,需要提供的字段
    public var showType:String?             // 路由展示方式：[modal 或者 navigator]
    public var openAnimator:String?         // 打开当前节点的动画
    public var closeAnimator:String?        // 退出当前节点的动画
    
    public var path:String?                 // 路由节点的路径,上层封装为只读
    public var fragment:Int? = 0               // 表示相同链路下的页面数量,上层封装为只读
    
    // 路由私有部分,[每个节点对应的实例可能不止一个]
    public var launchData:Any?              // 启动页面的复杂数据模型
    public var backAction:((Any?)->Void)?   // 回调
    weak var viewController: RouterControllerMixin?
    
    
    init(name:String, instance:String, unique:Bool = false, meta:[String : Any]? = nil, showType:String? = "navigator", openAnimator:String? = nil, closeAnimator:String? = nil) {
        self.name = name
        self.instance = instance
        self.unique = unique
        self.meta = meta
        self.showType = showType
        self.openAnimator = openAnimator
        self.closeAnimator = closeAnimator
    }
}



// 获取工程名字的方法
private var programName = ""
private func nameForProgram()->String{
    if programName.isEmpty {
        programName = Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String
    }
    return programName
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//   DY://host/path/value?paras#fragment ,其中DY一个通用标识，host,单应用程序从来都不关注schemce和host，path代表页面层级深度，每个路径对应一个页面的值， value 代表页面， paras:参数列表，fragment一般作为页码，但是可以作为相同页面的数量

public class Router{
    public static var nodes:[String:RouterNode] = [:]  //所有注册的基础节点
    public static var instanceNodes:[String:[RouterNode]] = [:] // 当前实例节点
    private static weak var topVC:UINavigationController? // 顶层控制器[整体UI体系设计]
    public static var flutterEngine:FlutterEngine?
public class func registerNode(node:RouterNode){
    if let _ = nodes[node.name] {
        assert(false,"当前节点:\(node.name)已存在")
        return
    }
    self.nodes[node.name] = node   // 添加节点
}
    
    public static var rootVC:UINavigationController {
        if let _ = topVC {
            return topVC!
        }
        var node = RouterNode(name: "vc", instance: "BaseTabbarController")
        let prName = nameForProgram()
        let clsName = prName + "." + node.instance
        let cls = NSClassFromString(clsName) as? UIViewController.Type
        let controller = cls!.init()
        node.viewController = controller as? RouterControllerMixin
        (controller as? RouterControllerMixin)!.routerNode = node
        instanceNodes[node.name] = [node]
        let nav = UINavigationController(rootViewController: controller)
        nav.setNavigationBarHidden(true, animated: false)
        topVC = nav
        flutterEngine = FlutterEngine.init(name: "my_flutter")
        flutterEngine?.run()
        GeneratedPluginRegistrant.register(with: flutterEngine!)
        if let register = flutterEngine?.registrar(forPlugin: "flutter_mix") {
            FlutterMixPlugin.register(with: register)
        }
        return nav
    }
    
    private class func generateARoute(name: String,launchData:Any? = nil,backAction:((Any?)->Void)? = nil) -> RouterNode? {
        let baseNode = nodes[name]
        if baseNode == nil {
            assert(false,"节点未注册\(name)")
            return nil;
        }
        var newNode = RouterNode(name: name, instance: baseNode?.instance ?? "", unique: baseNode?.unique ?? false, meta: baseNode?.meta, showType: baseNode?.showType, openAnimator: baseNode?.openAnimator, closeAnimator: baseNode?.closeAnimator)
        newNode.launchData = launchData
        newNode.backAction = backAction
        return newNode
    }
    
    // 生成一个路由控制器
    public class func generateRouteController(name:String, launchData:Any? = nil,backAction:((Any?)->Void)? = nil) -> UIViewController? {
        var newNode = generateARoute(name: name, launchData: launchData, backAction:backAction)
        if newNode == nil {
            return nil;
        }
        let prName = nameForProgram()
        let clsName = prName + "." + newNode!.instance
        let cls = NSClassFromString(clsName) as? UIViewController.Type
        if cls == nil {
            assert(false,"当前页面不存在")
            return nil;
        }
        let controller = cls!.init()
        if !(controller is RouterControllerMixin) {
            assert(false, "页面没有符合路由协议")
            return nil;
        }
        newNode!.viewController = controller as? RouterControllerMixin
        (controller as? RouterControllerMixin)?.routerNode = newNode
        return controller;
    }

    // 打开一个新节点，[节点必须在路由表里注册]
    public class func push(name:String, needNavigator:Bool = false, launchData:Any? = nil,backAction:((Any?)->Void)? = nil){
        var newNode = generateARoute(name: name, launchData: launchData, backAction: backAction)
        if newNode == nil {
            return
        }
        var instance = instanceNodes[name]
        if instance == nil {
            instance = []
        }
        var newInstance:[RouterNode] = []
        instance?.forEach({ item in
            if item.viewController != nil {
                newInstance.append(item)
            }
        })
        instance = newInstance
        let prName = nameForProgram()
        let clsName = prName + "." + newNode!.instance
        let cls = NSClassFromString(clsName) as? UIViewController.Type
        
        if cls == nil {
            assert(false,"当前页面不存在")
            return
        }
        
        // TODO: 初始化的方式可扩展
        let controller = cls!.init()
        if !(controller is RouterControllerMixin) {
            assert(false, "页面没有符合路由协议")
            return
        }
       
        newNode!.viewController = controller as? RouterControllerMixin
        (controller as? RouterControllerMixin)?.routerNode = newNode
        instance?.append(newNode!)
        topVC?.pushViewController(controller, animated: true)
    }

    // 退出节点的方式1，还有种方式是手势侧滑
    class func pop() -> Void {
        topVC?.popViewController(animated: true)
    }
    
    // 退到指定的路由
    class func popTo(name:String) {
        
    }

}
